﻿#include "TextGraphicsItem.h"
#include "GraphicsDef.h"
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include <QFocusEvent>

namespace OfUI {

	TextGraphicsItem::TextGraphicsItem(QGraphicsItem *parent)
		: BaseGraphicsItem(parent)
		, m_bAdding(true)
		, m_eSelType(SELECT_NONE)
	{
		setType(ItemType::TEXT);
	}

	TextGraphicsItem::~TextGraphicsItem()
	{
	}

	void TextGraphicsItem::setText(const QString& sText)
	{
		prepareGeometryChange();
		m_text = sText;
		emit signalDataChanged();
	}

	QString TextGraphicsItem::getText() const
	{
		return m_text;
	}

	void TextGraphicsItem::setPos(const QPointF& pos)
	{
		prepareGeometryChange();
		m_pos = pos;
		emit signalDataChanged();
	}

	QPointF TextGraphicsItem::getPos() const
	{
		return m_pos;
	}

	bool TextGraphicsItem::isAdding() const
	{
		return m_bAdding;
	}

	bool TextGraphicsItem::isEditing() const
	{
		return SELECT_NONE != m_eSelType;
	}

	bool TextGraphicsItem::isVaild() const
	{
		return !m_text.isEmpty();
	}

	BaseGraphicsItem::MouseDragType TextGraphicsItem::select(const QPointF& point, int* selType /*= nullptr*/) const
	{
		MouseDragType eDragType = DRAG_NONE;
		SelectType eSelectType = SELECT_NONE;

		if (getTextRect().contains(point))
		{
			eDragType = DRAG_EDIT;
			eSelectType = SELECT_TEXT;
		}
		if (selType)
		{
			*selType = eSelectType;
		}
		return eDragType;
	}

	void TextGraphicsItem::cursor(const QPointF& point, QCursor& cursor) const
	{
		if (BaseGraphicsItem::DRAG_NONE != select(point))
		{
			cursor = Qt::SizeAllCursor;
		}
	}

	void TextGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
	{
		if (Qt::LeftButton == event->button())
		{
			m_pressMousePos = event->scenePos();

			if (isAdding())
			{
				m_pos = m_pressMousePos;
				m_eSelType = SELECT_TEXT;
			}
			else
			{
				int nType = SELECT_NONE;
				if (BaseGraphicsItem::DRAG_NONE != select(event->scenePos(), &nType))
				{
					m_eSelType = static_cast<SelectType>(nType);
					return;
				}
			}
		}
		QFocusEvent focusEvent(QEvent::FocusOut, Qt::OtherFocusReason);
		focusOutEvent(&focusEvent);
	}

	void TextGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
	{
		QFocusEvent focusEvent(QEvent::FocusOut, Qt::OtherFocusReason);
		focusOutEvent(&focusEvent);
	}

	void TextGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
	{
		if (SELECT_NONE == m_eSelType)
			return;

		QPointF mousePos = event->scenePos();
		QRectF sceneRect = scene()->sceneRect();
		// 保证鼠标在场景内
		mousePos.setX(qMin(mousePos.rx(), sceneRect.right()));
		mousePos.setY(qMin(mousePos.ry(), sceneRect.bottom()));
		mousePos.setX(qMax(mousePos.rx(), sceneRect.left()));
		mousePos.setY(qMax(mousePos.ry(), sceneRect.top()));

		setPos(m_pos + mousePos - m_pressMousePos);
		m_pressMousePos = mousePos;
	}

	void TextGraphicsItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
	{
		if (Qt::LeftButton == event->button())
		{
			emit signalEditText();
		}
	}

	void TextGraphicsItem::focusOutEvent(QFocusEvent *event)
	{
		Q_UNUSED(event);
		if (isAdding())
		{
			m_bAdding = false;
			emit signalAddFinished();
		}
		m_eSelType = SELECT_NONE;
	}

	QRectF TextGraphicsItem::boundingRect() const
	{
		QRectF rectF = getTextRect().adjusted(-5, -5, 5, 5);
		return rectF;
	}

	void TextGraphicsItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
	{
		Q_UNUSED(option);
		Q_UNUSED(widget);

		if (this->scene())
		{
			painter->save();
			painter->setRenderHint(QPainter::Antialiasing);

			// 通过反向缩放painter实现矢量绘制效果
			double dViewScale = getViewScale();
			painter->scale(1 / dViewScale, 1 / dViewScale);

			// painter缩小，则绘制坐标放大，保证显示位置不变
			QRectF textRect = getTextRect();
			textRect = QRectF(textRect.topLeft() * dViewScale, textRect.bottomRight() * dViewScale);

			painter->setFont(getFont());
			painter->setPen(getPen(getState()));
			painter->drawText(textRect, Qt::AlignLeft | Qt::AlignTop, m_text);
			painter->restore();
		}
	}

	QRectF TextGraphicsItem::getTextRect() const
	{
		QStringList splitText = m_text.split('\n');
		int nTextCol = splitText.count();

		QFontMetricsF fm(getFont());
		double dWidth = 0;
		for (QString sText : splitText)
		{
			dWidth = qMax(dWidth, fm.width(sText) / getViewScale());
		}
		double dHeight = fm.height() * nTextCol / getViewScale();

		if (nTextCol > 1)
			dHeight += fm.leading() * (nTextCol - 1) / getViewScale();

		return QRectF(m_pos.x(), m_pos.y(), dWidth, dHeight);
	}

}
